Skip to content

fix(cli): guard nil file panic in generated download commands - #1241

Open
jablan wants to merge 1 commit into
mainfrom
fix/cli-locales-download-nil-file-panic
Open

fix(cli): guard nil file panic in generated download commands#1241
jablan wants to merge 1 commit into
mainfrom
fix/cli-locales-download-nil-file-panic

Conversation

@jablan

@jablan jablan commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

Summary

A user reported that the latest CLI release panics on phrase locales download when a --tags filter matches zero translations:

$ phrase locales download --id en-US --project_id ... -t ... --file_format properties --tags foo
panic: runtime error: invalid memory address or nil pointer dereference
...
github.com/phrase/phrase-cli/cmd.initLocaleDownload.func1(...)
        /go/src/github.com/phrase/phrase-cli/cmd/api_locales.go:410 +0xdef

This is a sibling issue to #1235 (fixed in pull.go), but in a different code path: the standalone, per-endpoint phrase locales download command generated from openapi-generator/templates/cli/api.handlebars.

Root cause: the API returns 200 OK with an empty body when a filter matches no translations. The SDK's decode() leaves the *os.File result nil in that case with no error — a valid empty export, not a failed download. The generated command unconditionally called data.Close() / data.Name() on that nil file, causing a nil pointer dereference.

Since cmd/api_*.go files are generated (and gitignored — never committed), the fix has to live in the Handlebars template itself, which is shared by every generated command whose return type is *os.File. So this also covers other download-style endpoints beyond locale download, not just the one in the report.

Fix

Wrap the file-handling block in api.handlebars with a data != nil guard, mirroring the same fix already applied to copyToDestination in pull.go.

Test plan

  • Added spec/locales_download_spec.rb, an integration spec that mocks the download endpoint returning 200 with an empty body and runs the actual built phrase-cli binary.
  • Regenerated the CLI locally (npm run generate.go && npm run generate.cli) and confirmed the new spec fails with the exact reported panic against the pre-fix template, and passes after applying the fix.
  • Confirmed normal (non-empty) downloads are unaffected.
  • Full Ruby spec suite (38 examples) green.

🤖 Generated with Claude Code

The API returns 200 with an empty body when a download's tags filter
matches zero translations. The SDK's decode() leaves the *os.File
result nil in that case with no error, but the generated download
commands unconditionally called data.Close()/data.Name() on it,
causing a nil pointer dereference panic, e.g.:

  phrase locales download --id en-US --project_id ... \
    --file_format properties --tags <tag-matching-nothing>

Same root cause as the earlier pull.go fix, but in the openapi-generator
CLI template, which is shared by every generated command whose return
type is *os.File - so this also covers other download-style endpoints
beyond locale download.

Added spec/locales_download_spec.rb, which reproduces the exact crash
against a mock server. Confirmed it fails with the reported panic
against the pre-fix generated code and passes after regenerating with
the template fix; full spec suite (38 examples) still green.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@github-actions

Copy link
Copy Markdown
Contributor

API changelog (oasdiff)

Doc-only edits (descriptions, examples) do not appear here.

No changes detected

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants